#include "ano_init.h"
#include "main.h"
#include "usart.h"
#include "stm32f1xx_it.h"

uint8_t USART2_TX_BUF[MAX_TX_LEN];   // my_printf的发送缓冲，下文详述其作用。
volatile uint8_t USART1_TX_FLAG = 0; // USART发送标志，启动发送时置1，加volatile防编译器优化
uint8_t u1rxbuf[MAX_RX_LEN];         // 数据接收缓冲1
uint8_t u2rxbuf[MAX_RX_LEN];         // 数据接收缓冲2
uint8_t WhichBufIsReady = 0;         // 双缓存指示器。
// 0:u1rxbuf 被DMA占用接收,  u2rxbuf 可以读取.
// 0:u2rxbuf 被DMA占用接收,  u1rxbuf 可以读取.

uint8_t *p_IsOK = u2rxbuf;        // 指针——指向可以读取的那个缓冲
uint8_t *p_IsToReceive = u1rxbuf; // 指针——指向被占用的那个缓冲


/*引入外部所用的DMA句柄*/
extern DMA_HandleTypeDef hdma_usart2_rx;

/// @brief 匿名协议串口配置初始化
/// @param  无
void ano_init(void)
{
    // 开启串口1空闲中断
    __HAL_UART_ENABLE_IT(&ANO_UART, UART_IT_IDLE);
    // 开启DMA发送通道的发送完成中断，才能实现封装发送函数里面的等待功能

    // 清除空闲标志位，防止中断误入
    __HAL_UART_CLEAR_IDLEFLAG(&ANO_UART);

    // 立即就要打开DMA接收
    // 不然DMA没有提前准备，第一次接收的数据是读取不出来的
    HAL_UART_Receive_DMA(&ANO_UART, p_IsToReceive, MAX_RX_LEN);
}

/// @brief 接受并处理不定长数据
/// @param  huartx 串口句柄
/// @param hdma_usartx_rx 串口DMA句柄
/// @return 本次接受到的数据长度 单位:字节
int32_t rev_dma_data(void)
{
    if (RESET != __HAL_UART_GET_FLAG(&ANO_UART, UART_FLAG_IDLE))
    {
        // 我记得好像HAL库里面没有给串口空闲中断预留专用的回调函数 qaq
        // __HAL_UART_CLEAR_IDLEFLAG();
        // 这一部分其实在 HAL_UART_IRQHandler() 也完成了。

        HAL_UART_DMAStop(&ANO_UART); // 把DMA接收停掉，防止速度过快导致中断重入，数据被覆写

        uint32_t data_length = MAX_RX_LEN - __HAL_DMA_GET_COUNTER(&ANO_UART_DMA);
        // 数据总长度=极限接收长度-DMA剩余的接收长度
        if (WhichBufIsReady) // WhichBufIsReady=1
        {
            p_IsOK = u2rxbuf;        // u2rxbuf 可以读取，就绪指针指向它。
            p_IsToReceive = u1rxbuf; // u1rxbuf 作为下一次DMA存储的缓冲，占用指针指向它。
            WhichBufIsReady = 0;     // 切换一下指示器状态
        }
        else // WhichBufIsReady=0
        {
            p_IsOK = u1rxbuf;        // u1rxbuf 可以读取，就绪指针指向它。
            p_IsToReceive = u2rxbuf; // u2rxbuf 作为下一次DMA存储的缓冲，占用指针指向它。
            WhichBufIsReady = 1;     // 切换一下指示器状态
        }
        // 从下面开始可以处理你接收到的数据啦！

            ano_cmd_rev(p_IsOK);

        /// 不管是复制也好，放进去队列也罢，处理你接收到的数据的代码建议从这里结束
        // memset((uint8_t *)p_IsToReceive, 0, MAX_RX_LEN); // 把接收数据的指针指向的缓冲区清空
        return data_length;
    }
    else
        return (-1);
}

/**
 * 跳转到指定地址的函数
*/
void boot_jump_to_run(uint32_t addr)
{
  uint32_t jump_addr;

  if(((*(uint32_t*)addr)&0x2FFE0000)==0x20000000)
  {
    jump_addr = *(uint32_t*)(addr+4);
    __set_MSP(*(uint32_t*)addr);
    ((void (*)(void))jump_addr)();
  }
}